﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TaskManager
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                //设置应用程序处理异常方式：ThreadException处理
                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
                //处理UI线程异常
                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                //处理非UI线程异常
                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

                #region 应用程序的主入口点

                updateFile();   // 执行文件更新逻辑

                // 若不存在已经运行的实例，则启动运行
                Process Instance = RunningInstance();
                if (Instance != null)
                {
                    Instance.Kill();
                    Instance = null;
                }

                //bool update = false;
                //update = checkUpdate();
                if (Instance == null && !checkUpdate())
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new loginForm());

                    //Application.Run(new Form_main()); 

                    //Application.Run(new floatMenu());
                    //Application.Run(new TaskManage());

                    //Application.Run(new TestForm());

                    //Application.Run(new MessageForm());

                    //Application.Run(new NoticeForm());
                }
                #endregion
            }
            catch (Exception ex)
            {
                string str = GetExceptionMsg(ex, string.Empty);
                //MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        // 保存日志信息
        public static void saveLog(string data)
        {
            string name = "log\\" + Tool.TimeNow().Replace(":", ".").Replace(" ", "_");
            loginForm.SaveTxt(data, name);

            loginForm.Instance.Close();     // 关闭登录界面
        }

        // 重启当前应用
        public static void restartOnError()
        {
            String date = Tool.getDate(DateTime.Now);       // 获取日期，如 2005-06-07

            // 获取重启次数信息
            String Str = Tool.RegistryStrValue(@"Scimence\TaskManager\Set", "异常重启次数");
            if (!Str.StartsWith(date + ";")) Str = date + ";" + 0;
            
            // 获取重启次数，连续异常时最多重启2次
            int times = Int32.Parse(Str.Split(';')[1]);
            if (times < 2)
            {
                times++;
                Str = date + ";" + times;

                Tool.RegistrySave(@"Scimence\TaskManager\Set", "异常重启次数", Str);

                string path = Application.ExecutablePath;
                System.Diagnostics.Process.Start(path);
            }
        }

        /// <summary>
        /// 获取与当前进程TaskManager同名的其它进程
        /// </summary>
        public static Process RunningInstance()
        {
            Process current = Process.GetCurrentProcess();
            Process[] processes1 = Process.GetProcessesByName(current.ProcessName); // "TaskManager.vshost"
            Process[] processes2 = Process.GetProcessesByName(current.ProcessName.Replace(".vshost", ""));
            //Process[] processes2 = Process.GetProcessesByName(current.ProcessName);

            List<Process> processes = new List<Process>();
            foreach (Process process in processes1) processes.Add(process);
            foreach (Process process in processes2) processes.Add(process);


            foreach (Process process in processes)
            {
                if (process.Id != current.Id)
                {
                    string processName = System.IO.Path.GetFileName(process.MainModule.FileName).Replace(".vshost", "");
                    string currentName = System.IO.Path.GetFileName(current.MainModule.FileName).Replace(".vshost", "");

                    if (processName.Equals(currentName))
                    {
                        return process;
                    }
                }
            }

            return null;
        }


        public static String curVersion = "20161118";  // 当前软件版本信息
        
        // 检查工具是否有更新
        private static bool checkUpdate()
        {
            try
            {
                // 获取版本配置信息
                Data_Verison V = new Data_Verison();

                string serverIP = Tool.RegistryStrValue(@"Scimence\TaskManager\Set", "服务器");
                string versionConfig = HttpTool.GetHtml2("http://git.oschina.net/scimence/TaskManager/raw/master/Files/versionInfo.txt", Encoding.UTF8);
                if (versionConfig.Equals("")) versionConfig = HttpTool.GetHtml2("http://" + serverIP + "/client.php");  // "http://task.joymeng.com/client.php"
                if (!versionConfig.Equals("")) V = Data_Verison.Parse(versionConfig);


                // 检测到新的版本
                if (Tool.Shortdate_cmp(V.version, curVersion) > 0)
                {
                    bool ok = true;

                    // 非强制更新时，显示更新提示
                    if (!V.forceUpdate) ok = (MessageBox.Show("检测到新的版本，现在更新？", "版本更新", MessageBoxButtons.OKCancel) == DialogResult.OK);

                    if (ok)
                    {
                        // 获取更新插件名
                        //string update_EXE = updateFile();
                        string update_EXE = System.AppDomain.CurrentDomain.BaseDirectory + "UpdateFiles.exe";
                        if (System.IO.File.Exists(update_EXE))
                        {
                            // 获取url中对应的文件名
                            //string fileName = System.AppDomain.CurrentDomain.BaseDirectory + System.IO.Path.GetFileName(V.url);
                            string fileName = System.AppDomain.CurrentDomain.BaseDirectory + "乐堂OA客户端.exe";

                            // 生成更新时的显示信息
                            String info = "当前版本：" + curVersion + "\r\n" + "最新版本：" + V.version + "\r\n" + V.Info;

                            // 调用更新插件执行软件更新逻辑
                            String arg = "\"" + V.url + "\"" + " " + "\"" + fileName + "\"" + " " + "true" + " " + "\"" + info + "\"";
                            System.Diagnostics.Process.Start(update_EXE, arg);

                            return true;
                        }
                        else MessageBox.Show("未找到更新插件：\r\n" + update_EXE);
                    }
                }

                return false;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }  // 未获取到版本信息
        }

        // 更新替换文件逻辑
        private static void updateFile()
        {
            string info = "更新UpdateFiles.exe\r\n";

            // 若文件不存在则自动创建
            string file1 = Tool.curDir() + "UpdateFiles.exe";
            string value = Tool.RegistryStrValue(@"Scimence\TaskManager\Set", "文件更新");
            if (!value.Contains(info) || !System.IO.File.Exists(file1))
            {
                Tool.RegistrySave(@"Scimence\TaskManager\Set", "文件更新", info);

                // UpdateFiles.exe文件资源
                Byte[] array = Properties.Resources.UpdateFiles.ToArray<Byte>();
                SaveFile(array, file1);
            }

            // 若不存在文件则自动创建
            string file2 = Tool.curDir() + "Newtonsoft.Json.dll";
            SaveFile(Properties.Resources.Newtonsoft_Json, file2);

            //// 用于SFTP文件操作
            //string file3 = Tool.curDir() + "Tamir.SharpSSH.dll";
            //SaveFile(Properties.Resources.Tamir_SharpSSH, file3);
        }


        /// <summary>
        /// 保存Byte数组为文件
        /// </summary>
        private static void SaveFile(Byte[] array, string path)
        {
            if (!System.IO.File.Exists(path))
            {
                // 创建输出流
                System.IO.FileStream fs = new System.IO.FileStream(path, System.IO.FileMode.Create);

                //将byte数组写入文件中
                fs.Write(array, 0, array.Length);
                fs.Close();
            }
        }

        /// <summary>
        /// 更新文件逻辑,判定文件是否处于运行状态，关闭并删除后，创建新的文件
        /// </summary>
        private static void outPutFile(Byte[] array, string pathName)
        {
            // 若文件正在运行，则从进程中关闭
            string fileName = System.IO.Path.GetFileName(pathName);
            KillProcess(fileName);

            // 删除原有文件
            if (System.IO.File.Exists(pathName)) System.IO.File.Delete(pathName);

            // 保存新的文件
            SaveFile(array, pathName);
        }

        /// <summary>
        /// 关闭名称为processName的所有进程
        /// </summary>
        public static void KillProcess(string processName)
        {
            Process[] processes = Process.GetProcessesByName(processName);

            foreach (Process process in processes)
            {
                if (process.MainModule.FileName == processName)
                {
                    process.Kill();
                }
            }
        }


        ///////--------------------------------------------------------------------------

        ///// <summary>
        ///// 应用程序的主入口点。
        ///// </summary>
        //[STAThread]
        //static void Main()
        //{
        //    try
        //    {
        //        //设置应用程序处理异常方式：ThreadException处理
        //        Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
        //        //处理UI线程异常
        //        Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
        //        //处理非UI线程异常
        //        AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

        //        #region 应用程序的主入口点
        //        Application.EnableVisualStyles();
        //        Application.SetCompatibleTextRenderingDefault(false);
        //        Application.Run(new Form1());
        //        #endregion
        //    }
        //    catch (Exception ex)
        //    {
        //        string str = GetExceptionMsg(ex, string.Empty);
        //        MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        //    }
        //}


        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            string str = GetExceptionMsg(e.Exception, e.ToString());
            //MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

            //bool ok = (MessageBox.Show(str, "系统错误，提交bug信息？", MessageBoxButtons.OKCancel, MessageBoxIcon.Error) == DialogResult.OK);
            //if (ok) sendBugToAuthor(str);

            checkUpdate();      // 捕获运行异常后，检测是否有版本更新
            //LogManager.WriteLog(str);
        }

        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            string str = GetExceptionMsg(e.ExceptionObject as Exception, e.ToString());
            //MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);

            //bool ok = (MessageBox.Show(str, "系统错误，提交bug信息？", MessageBoxButtons.OKCancel, MessageBoxIcon.Error) == DialogResult.OK);
            //if (ok) sendBugToAuthor(str);

            checkUpdate();      // 捕获运行异常后，检测是否有版本更新
            //LogManager.WriteLog(str);
        }

        /// <summary>
        /// 生成自定义异常消息
        /// </summary>
        /// <param name="ex">异常对象</param>
        /// <param name="backStr">备用异常消息：当ex为null时有效</param>
        /// <returns>异常字符串文本</returns>
        static string GetExceptionMsg(Exception ex, string backStr)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("****************************异常文本****************************");
            sb.AppendLine("【出现时间】：" + Tool.TimeNow());
            if (ex != null)
            {
                sb.AppendLine("【异常类型】：" + ex.GetType().Name);
                sb.AppendLine("【异常信息】：" + ex.Message);
                sb.AppendLine("【堆栈调用】：" + ex.StackTrace);

                sb.AppendLine("【异常方法】：" + ex.TargetSite);
            }
            else
            {
                sb.AppendLine("【未处理异常】：" + backStr);
            }
            sb.AppendLine("***************************************************************");

            string info = sb.ToString();


            saveLog(info);  // 保存运行异常信息
            restartOnError();      // 运行异常时，自动重启

            return info;
        }

        // 发送运行时出现的bug信息
        static void sendBugToAuthor(String bugInfo0)
        {
            String bugInfo = bugInfo0.Replace("\r\n", "_r_n");
            String tittle = "乐堂任务管理工具客户端，运行bug";
            String chekbugInfoSql = "SELECT COUNT(*) FROM `zt_bug` WHERE `title`='" + tittle + "' AND `steps` = '" + bugInfo + "'";
            String countInfo = Tool.Execute(chekbugInfoSql);    // 判断此条bug是否已存在

            MessageBox.Show("[" + countInfo + "]");
            if (countInfo.Equals("[{\"COUNT(*)\":\"0\"}]"))
            {
                String assignedTo = "wang.zhy";
                String newBugSql = "INSERT INTO `zt_bug`(`product`,`branch`,`module`,`project`,`plan`,`story`,`storyVersion`,`task`,`toTask`,`toStory`,`title`,`keywords`,`severity`,`pri`,`type`,`os`,`browser`,`hardware`,`found`,`steps`,`status`,`confirmed`,`activatedCount`,`mailto`,`openedBy`,`openedDate`,`openedBuild`,`assignedTo`,`assignedDate`,`resolvedBy`,`resolution`,`resolvedBuild`,`resolvedDate`,`closedBy`,`closedDate`,`duplicateBug`,`linkBug`,`case`,`caseVersion`,`result`,`testtask`,`lastEditedBy`,`lastEditedDate`,`deleted`) "+
                    "VALUES ( '2016','0','0','2016','0','0','1','0','0','0','" + tittle + "',' ','0',' ','others','','',' ','','" + bugInfo + "','active','0','0','','" + loginForm.userName + "','"+Tool.TimeNow()+"','trunk','" + assignedTo + "','0000-00-00 00:00:00','','','','0000-00-00 00:00:00','','0000-00-00 00:00:00','0','','0','0','0','0','','0000-00-00 00:00:00','0');";
                
                Tool.Execute(newBugSql); // 发送bug信息
            }
        }
    }
}
